---
title: Templates and Generic Programming
---

Templates are a powerful feature in C++ that allow you to write generic code that works with different data types without having to rewrite the same code for each type. This is a form of **generic programming**, which aims to write algorithms and data structures that are independent of the specific data types they operate on. While JavaScript achieves a form of genericity through its dynamic typing, C++ templates provide compile-time type safety and performance.

## Function Templates

A **function template** defines a family of functions that can operate on different data types. The compiler generates actual functions (template instantiations) based on the types used when the template is called.

<UniversalEditor title="Function Template Comparison" compare={true}>
```javascript !! js
// JavaScript: Generic function (dynamic typing handles genericity)
function identity(value) {
  return value;
}

console.log(identity(123)); // 123
console.log(identity("hello")); // "hello"
console.log(identity(true)); // true

function add(a, b) {
  return a + b;
}

console.log(add(5, 3)); // 8
console.log(add("Hello ", "World")); // "Hello World"
```

```cpp !! cpp
// C++: Function Templates
#include <iostream>
#include <string>

// Function template for identity
template <typename T>
T identity(T value) {
  return value;
}

// Function template for add
template <typename T>
T add(T a, T b) {
  return a + b;
}

int main() {
  // std::cout << identity(123) << std::endl; // T becomes int
  // std::cout << identity("hello") << std::endl; // T becomes const char*
  // std::cout << identity(true) << std::endl; // T becomes bool

  // std::cout << add(5, 3) << std::endl; // T becomes int
  // std::cout << add(5.5, 3.2) << std::endl; // T becomes double
  // std::cout << add(std::string("Hello "), std::string("World")) << std::endl; // T becomes std::string

  return 0;
}
```
</UniversalEditor>

## Class Templates

A **class template** defines a family of classes that can store and manipulate objects of different data types. This is commonly used for generic data structures like lists, stacks, queues, etc.

<UniversalEditor title="Class Template Comparison" compare={true}>
```javascript !! js
// JavaScript: Generic class (dynamic typing)
class Box {
  constructor(value) {
    this.value = value;
  }

  getValue() {
    return this.value;
  }
}

const intBox = new Box(10);
console.log(intBox.getValue()); // 10

const stringBox = new Box("text");
console.log(stringBox.getValue()); // "text"
```

```cpp !! cpp
// C++: Class Templates
#include <iostream>
#include <string>

template <typename T>
class Box {
public:
  T value;

  Box(T val) : value(val) {}

  T getValue() {
    return value;
  }
};

int main() {
  Box<int> intBox(10); // Instantiate Box with int
  // std::cout << intBox.getValue() << std::endl; // 10

  Box<std::string> stringBox("text"); // Instantiate Box with std::string
  // std::cout << stringBox.getValue() << std::endl; // "text"

  return 0;
}
```
</UniversalEditor>

## Template Specialization and Partial Specialization

Sometimes, a generic template might not be optimal or even correct for certain specific types. **Template specialization** allows you to provide a completely different implementation for a specific type. **Partial specialization** allows you to provide a specialized implementation for a subset of template arguments.

### Full Specialization

<UniversalEditor title="Full Template Specialization" compare={true}>
```javascript !! js
// JavaScript: Achieved with conditional logic or type checking
function processData(data) {
  if (typeof data === 'string') {
    return `Processing string: ${data.toUpperCase()}`;
  } else if (typeof data === 'number') {
    return `Processing number: ${data * 2}`;
  } else {
    return `Processing generic: ${data}`;
  }
}

console.log(processData("hello"));
console.log(processData(10));
```

```cpp !! cpp
// C++: Full Template Specialization
#include <iostream>
#include <string>

template <typename T>
void printValue(T value) {
  // std::cout << "Generic print: " << value << std::endl;
}

// Full specialization for int
template <>
void printValue<int>(int value) {
  // std::cout << "Specialized print for int: " << value * 2 << std::endl;
}

// Full specialization for std::string
template <>
void printValue<std::string>(std::string value) {
  // std::cout << "Specialized print for string: " << value << " (length: " << value.length() << ")" << std::endl;
}

int main() {
  // printValue(5); // Calls specialized int version
  // printValue(3.14); // Calls generic double version
  // printValue(std::string("test")); // Calls specialized std::string version
  return 0;
}
```
</UniversalEditor>

### Partial Specialization (for Class Templates)

Partial specialization is only applicable to class templates, not function templates.

<UniversalEditor title="Partial Template Specialization" compare={true}>
```javascript !! js
// JavaScript: No direct equivalent, but similar logic can be achieved
// by having different implementations based on the types of arguments.
// This is handled by the dynamic nature of JavaScript.
```

```cpp !! cpp
// C++: Partial Template Specialization (for class templates)
#include <iostream>

template <typename T1, typename T2>
class Pair {
public:
  Pair(T1 v1, T2 v2) {
    // std::cout << "Generic Pair created." << std::endl;
  }
};

// Partial specialization for Pair<T, int>
template <typename T>
class Pair<T, int> {
public:
  Pair(T v1, int v2) {
    // std::cout << "Partial specialized Pair<T, int> created." << std::endl;
  }
};

int main() {
  // Pair<double, char> p1(1.1, 'a'); // Calls generic Pair
  // Pair<double, int> p2(2.2, 10); // Calls partial specialized Pair<T, int>
  return 0;
}
```
</UniversalEditor>

## Variadic Templates

**Variadic templates** allow functions or classes to accept an arbitrary number of arguments of varying types. This is useful for functions like `printf` or for building custom logging mechanisms.

<UniversalEditor title="Variadic Template Comparison" compare={true}>
```javascript !! js
// JavaScript: Rest parameters handle variadic arguments
function log(...args) {
  console.log(...args);
}

log("Hello", 123, true);
log("Only one argument");
```

```cpp !! cpp
// C++: Variadic Templates
#include <iostream>

// Base case for recursion
void log() {
  // std::cout << std::endl;
}

// Recursive variadic template function
template <typename T, typename... Args>
void log(T firstArg, Args... args) {
  // std::cout << firstArg << " ";
  log(args...); // Recursive call
}

int main() {
  // log("Hello", 123, true);
  // log("Only one argument");
  return 0;
}
```
</UniversalEditor>

## Template Metaprogramming Basics

**Template metaprogramming (TMP)** is a technique where templates are used to perform computations at compile time rather than runtime. This can lead to highly optimized code, but it can also be complex and difficult to debug.

Common uses include:
*   Compile-time computations (e.g., factorial, Fibonacci series).
*   Type traits (querying properties of types).
*   Generating code based on types.

<UniversalEditor title="Template Metaprogramming Example" compare={true}>
```javascript !! js
// JavaScript: Compile-time computation is not a native concept.
// All computations are runtime.
function factorial(n) {
  if (n === 0) return 1;
  return n * factorial(n - 1);
}

console.log(factorial(5)); // 120
```

```cpp !! cpp
// C++: Template Metaprogramming (Compile-time Factorial)
#include <iostream>

template <int N>
struct Factorial {
  static const int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
  static const int value = 1;
};

int main() {
  // Compile-time calculation
  // std::cout << "Factorial of 5: " << Factorial<5>::value << std::endl; // 120
  return 0;
}
```
</UniversalEditor>

## Comparison with JavaScript Generics

JavaScript does not have a formal "generics" system like C++ templates. Its dynamic typing system inherently provides a form of genericity:

*   **Dynamic Typing:** Functions and classes can operate on values of any type without explicit type parameters. The type checking happens at runtime.
*   **Flexibility:** This offers great flexibility and reduces boilerplate code.
*   **Runtime Errors:** However, type-related errors are caught at runtime, not compile time.

C++ templates, in contrast, provide:
*   **Compile-time Genericity:** Types are checked at compile time, leading to earlier error detection and better performance.
*   **Type Safety:** Ensures that operations are valid for the types being used.
*   **Code Bloat (potential):** Each template instantiation generates separate code, which can increase executable size.

## Template Best Practices

1.  **Keep it Simple:** Use templates when true genericity is needed; avoid over-engineering.
2.  **Separate Declaration and Definition (for larger templates):** For class templates, it's common to put declarations in a `.h` file and definitions in a `.tpp` or `.hpp` file, then include the `.tpp` at the end of the `.h` file. For function templates, definitions are usually in the header.
3.  **Use `typename` vs. `class`:** `typename` is generally preferred for template type parameters, especially when dealing with dependent types.
4.  **Concept-based Constraints (C++20):** Use C++20 Concepts to constrain template parameters, making template errors more readable and providing better compile-time checks.
5.  **Avoid Excessive Metaprogramming:** While powerful, TMP can make code hard to read and debug. Use it judiciously.

---

### Practice Questions:
1.  Explain the purpose of function templates and class templates in C++. Provide a simple example of each.
2.  When would you use template specialization? Describe a scenario where it would be beneficial.
3.  How does C++'s template system differ from the way JavaScript achieves genericity? Discuss the advantages and disadvantages of each approach.

### Project Idea:
*   Implement a generic `Stack` class template in C++ that can store elements of any data type. Include methods like `push`, `pop`, `top`, and `isEmpty`. Demonstrate its usage with `int`, `double`, and `std::string` types.
